package com.demo.javaee.ref_type;

import org.apache.poi.poifs.nio.CleanerUtil;

import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 虚引用: get不到, 不是给业务人员用的, 给垃圾回收器用的, 用于跟踪堆外内存
 * @author shenguangyang
 */
public class PhantomReferenceDemo {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<Test> QUEUE = new ReferenceQueue<>();

    public static class Test {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("----------------finalize");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        PhantomReference<Test> pr = new PhantomReference<>(new Test(), QUEUE);

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024 * 1024);
        new Thread(() -> {
            while (true) {
                try {
                    LIST.add(new byte[1024 * 1024]);
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(pr.get());
                    System.gc();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        }).start();

        // 垃圾回收线程
        new Thread(() -> {
            while (true) {
                Reference<? extends Test> poll = QUEUE.poll();
                if (poll != null) {
                    try {
                        System.out.println("清理堆外内存");
                        CleanerUtil.getCleaner().freeBuffer(byteBuffer);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("虚引用对象被jvm回收了 ---- " + poll);
                }
            }
        }).start();
        TimeUnit.SECONDS.sleep(100);
    }
}
